﻿using SaaS.Cache.Auths;
using SaaS.Core;
using SaaS.Model.Dto.Auths;
using SaaS.Model.Entity.Auths;
using SaaS.Model.Enums;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using XCore.Dependency;
using XCore.Encryption;
using XCore.Extensions;
using XCore.Web.Jwt;
using SaaS.Model.Dto.Systems;
using SaaS.Core.Helper;

namespace Web.System.Services.Systems
{
    /// <summary>
    /// 总管理员操作员
    /// </summary>
    public class AdminAppService : SystemApplicationServiceBase, ISingletonDependency
    {
        private readonly SystemAuthCacheService _systemAuthCacheService;
        public AdminAppService(SystemAuthCacheService systemAuthCacheService)
        {
            _systemAuthCacheService = systemAuthCacheService;
        }
        /// <summary>
        /// 修改管理员角色
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public bool Edit(int id, int roleId)
        {
            return Repository.Update<SystemAdmin, int>(id, c => c.RoleId, roleId) && Logger.Log("更新管理员角色", SystemLoggerSource.Admin);
        }
        /// <summary>
        /// 创建用户
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public bool Create(string username, string name, int roleId)
        {
            if (!CheckHelper.CheckUserName(username, out string message)) throw new SystemException($"用户名输入有误：{message}", SystemLoggerSource.Admin);
            if (SDC.SystemAdmins.Any(c => c.UserName == username)) throw new SystemException("用户名已存在", SystemLoggerSource.Admin);
            SystemAdmin entity = new SystemAdmin
            {
                RoleId = roleId,
                UserName = username,
                Name = name,
                Password = string.Empty,
                Avatar = string.Empty,
            };
            int adminId = Repository.InsertAndGetId(entity);
            entity.Password = PwdEncryption.Encryption(CoreSetting.DefaultPassword, adminId);
            _systemAuthCacheService.SaveSystemAdminInfo(entity);
            return Repository.Update<SystemAdmin, string>(adminId, c => c.Password, entity.Password) && Logger.Log("添加管理员用户", SystemLoggerSource.Admin);
        }

        /// <summary>
        /// 管理员登录
        /// </summary>
        /// <param name="username"></param>
        /// <param name="password"></param>
        /// <returns></returns>
        public JWTResult Login(string username, string password)
        {
            if (!CheckHelper.CheckUserName(username, out string message)) throw new SystemException($"用户名输入有误：{message}", SystemLoggerSource.Login);
            if (!(password.Length >= 6 && password.Length < 32)) throw new SystemException("密码长度为6~32位字符", SystemLoggerSource.Login);
            //查询用户名与Id关系
            int adminId = _systemAuthCacheService.CheckUserName(username);
            if (adminId == 0) throw new SystemException($"登录名“{username}”不存在", SystemLoggerSource.Login);
            //先从缓存中查询，未保存至缓存，则走数据库
            SystemAdminModel admin = _systemAuthCacheService.GetSystemAdminInfo(adminId);
            if (!admin)
            {
                admin = SDC.SystemAdmins.FirstOrDefault(c => c.Id == adminId);
            }
            //检查状态
            if (admin.Status == UserStatus.Disable || admin.Status == UserStatus.Locking) throw new SystemException($"账号“{username}”已被:{admin.Status.GetDescription()}", SystemLoggerSource.Login);
            //检查密码
            if (!admin.Password.Equals(PwdEncryption.Encryption(password, admin.AdminId))) throw new SystemException($"账号“{username}”，密码错误", SystemLoggerSource.Login);
            //生成token
            string token = JWTHelper.CreateToken(new JWTOptions(CoreSetting.Audience, CoreSetting.Issuer, CoreSetting.Expire),
                new[] {
                    new Claim("AdminId", admin.AdminId.ToString()),
                    new Claim("UserName",admin.UserName),
                    new Claim("IsDefault",admin.IsDefault.ToString()),
                    new Claim("RoleId",admin.RoleId.ToString()),
                    });
            //进入缓存
            _systemAuthCacheService.SaveSystemAdminInfo(admin);
            _systemAuthCacheService.SaveSystemToken(admin.AdminId, token);
            Logger.Log(admin.AdminId, 0, $"[{username}]--登录成功", SystemLoggerSource.Login);
            return new JWTResult(token, CoreSetting.Expire);
        }
        /// <summary>
        /// 修改密码底层方法，所有修改用户密码必须进入此方法
        /// </summary>
        /// <param name="id"></param>
        /// <param name="password"></param>
        /// <returns></returns>
        private bool UpdatePassword(int id, string password)
        {
            var user = SDC.SystemAdmins.Where(c => c.Id == id).FirstOrDefault();
            if (user == null) throw new SystemException("用户错误", SystemLoggerSource.Admin);
            string encrypt = PwdEncryption.Encryption(password, id);
            if (SDC.SystemAdmins.Any(c => c.Id == id && c.Password == encrypt)) throw new SystemException("新密码与旧密码一致", SystemLoggerSource.Admin);
            return Repository.Update<SystemAdmin, string>(id, c => c.Password, encrypt) && Logger.Log(id, $"[{user.UserName}]--修改密码", SystemLoggerSource.Admin);
        }
        /// <summary>
        /// 重置密码，
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public bool ResetPwd(int id)
        {
            return UpdatePassword(id, CoreSetting.DefaultPassword);
        }
        /// <summary>
        /// 修改密码
        /// </summary>
        /// <param name="adminId"></param>
        /// <param name="password">新密码</param>
        /// <param name="usedPassword">旧密码</param>
        /// <returns></returns>
        public bool ResetPwd(int adminId, string password, string usedPassword)
        {
            var user = SDC.SystemAdmins.Where(c => c.Id == adminId).Select(c => new { c.Password }).FirstOrDefault();
            string encrypt = PwdEncryption.Encryption(usedPassword, adminId);
            if (!user.Password.Equals(encrypt)) throw new SystemException("旧密码输入有误", SystemLoggerSource.Admin);
            return UpdatePassword(adminId, password);
        }
        /// <summary>
        /// 上传头像
        /// </summary>
        /// <param name="adminId"></param>
        /// <param name="avatar"></param>
        /// <returns></returns>
        public bool UploadAvatar(int adminId, string avatar)
        {
            if (!SDC.SystemAdmins.Any(c => c.Id == adminId)) throw new SystemException(CoreSetting.Error_ID, SystemLoggerSource.Admin);
            return Repository.Update<SystemAdmin, string>(adminId, c => c.Avatar, avatar);
        }
        /// <summary>
        /// 删除管理员
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public bool Delete(int id)
        {
            if (SDC.SystemAdmins.Any(c => c.Id == id && c.IsDefault)) throw new SystemException("默认超级管理员不可删除", SystemLoggerSource.Admin);
            return Repository.Delete<SystemAdmin>(id) && Logger.Log(id, "删除管理员", SystemLoggerSource.Admin);
        }
        /// <summary>
        /// 获取所有管理员
        /// </summary>
        /// <param name="userId"></param>
        /// <param name="type"></param>
        /// <returns></returns>
        public IDictionary<int, string> GetDictionary()
        {
            return SDC.SystemAdmins.ToDictionary(c => c.Id, c => c.UserName);
        }
        /// <summary>
        /// 修改状态的底层方法，所有修改状态操作都要经过此方法
        /// </summary>
        /// <param name="id"></param>
        /// <param name="status"></param>
        /// <returns></returns>
        private bool UpdateStatus(int id, UserStatus status)
        {
            return Repository.Update<SystemAdmin, UserStatus>(id, c => c.Status, status) && Logger.Log(id, $"修改用户状态：{status}", SystemLoggerSource.Admin);
        }
        /// <summary>
        /// 锁定管理员
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public bool Lock(int id)
        {
            UserStatus? stauts = SDC.SystemAdmins.Where(c => c.Id == id).Select(c => (UserStatus?)c.Status).FirstOrDefault();
            if (!stauts.HasValue) throw new SystemException(CoreSetting.Error_ID, SystemLoggerSource.Admin);
            if (stauts.Value == UserStatus.Locking) throw new SystemException("当前用户状态为锁定", SystemLoggerSource.Admin);
            return this.UpdateStatus(id, UserStatus.Locking);
        }
        /// <summary>
        /// 解锁管理员
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public bool UnLock(int id)
        {
            UserStatus? stauts = SDC.SystemAdmins.Where(c => c.Id == id).Select(c => (UserStatus?)c.Status).FirstOrDefault();
            if (!stauts.HasValue) throw new SystemException(CoreSetting.Error_ID, SystemLoggerSource.Admin);
            if (stauts.Value == UserStatus.Normal) throw new SystemException("当前用户状态为正常", SystemLoggerSource.Admin);
            return this.UpdateStatus(id, UserStatus.Normal);
        }
    }
}
